{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Visualizing Image Data\n",
    "\n",
    "This notebook will demonstrate how to load and visualize astronomical images in the pywwt viewer."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Step 1: Setting up WWT\n",
    "\n",
    "First, we need to connect to the WWT app. If WWT isn't running yet, activate the JupyterLab command palette from the View menu, and select \"WorldWide Telescope\". Then all we need to do is run:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from pywwt.jupyter import connect_to_app\n",
    "wwt = await connect_to_app().becomes_ready()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now the `wwt` variable will let us talk to the WWT app. For example, the following command will make some things a bit easier for us farther down in this tutorial:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "wwt.foreground_opacity = 0"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We'll also set up a utility function to help us load data files stored alongside this notebook:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def datapath(*args):\n",
    "    from os.path import join\n",
    "    return join('data', *args)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Step 2: Visualizing a small FITS image\n",
    "\n",
    "We'll start by visualizing a WISE 12µm image towards the [Westerhout 5 star forming region](https://en.wikipedia.org/wiki/Westerhout_5) and taking a look at some of the advanced visualization options.\n",
    "\n",
    "Images, like data tables, are represented in WWT as \"layers\" that can be added to the view. With a standard FITS file, all you need to do is provide a file name:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "layer = wwt.layers.add_image_layer(datapath('w5.fits'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The viewer will automatically center and zoom to the image you've loaded.\n",
    "\n",
    "Once you've loaded a FITS image this way, WWT provides a standard set of controls over how exactly it's displayed. Clicking on the panel item labeled \"w5\" will reveal tools for controlling aspects of the image display like its opacity and the colormap. Clicking the target icons next to the \"Low cutoff\" and \"High cutoff\" settings will enter an interactive mode for adjusting these settings: clicking towards the top-left or top-right of the WWT window will substantially decrease or increase these parameters, respectively.\n",
    "\n",
    "For instance, by sliding the Opacity control, you can see how the image compares to the background survey. For this example, a good comparison is the IRAS dataset:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "wwt.background = 'IRIS: Improved Reprocessing of IRAS Survey (Infrared)'"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You can also control the same settings from Python. This code changes a bunch of them at once:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "layer.cmap = 'plasma'\n",
    "layer.vmin = 400\n",
    "layer.vmax = 1000\n",
    "layer.stretch = 'sqrt'\n",
    "layer.opacity = 0.9"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Note that there are currently some limitations in pywwt that limit the synchronization between the Python code and the WWT app, so mixing and matching the two interfaces can sometimes lead to unexpected results.\n",
    "\n",
    "After you're done playing around, let's reset the WWT widget:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "wwt.reset()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "# Step 3: Visualizing big images\n",
    "\n",
    "The image was used above was pretty, but small. If your data are bigger, WWT still has you covered.\n",
    "\n",
    "Here we'll visualize a larger image from the NRAO [VLASS][vlass] survey. The image we use has been specially processed to (1) be a bigger a challenge than the one before, but (2) still be usable on the very resource-constrained virtual machines that host our demonstration cloud notebooks. In actual work, when your kernel isn't running on a free temporary cloud service, resource limitations should almost never be an issue.\n",
    "\n",
    "[vlass]: https://science.nrao.edu/vlass\n",
    "\n",
    "First, we'll download the sample image to your kernel. This may take a little while."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from astropy.utils.data import download_file\n",
    "\n",
    "url = \"https://data1.wwtassets.org/packages/2022/01_demos/vlass2.1-ql-T01t30-J145214-363000.fits\"\n",
    "path = download_file(url)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "We can check and see that this file is more than 100 megabytes large:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "!ls -lh $path"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "If you had to wait to download the whole thing every time you wanted to view it, that would be pretty annoying!\n",
    "\n",
    "To view this file in WWT, we use the same pattern as above. This time, however, pywwt does some extra processing (\"tiling\") to enable quick visualization:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "layer = wwt.layers.add_image_layer(path)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This image contains [a pretty double radio galaxy][x] along the lower left edge which you can pull out by adjusting the data cuts. These settings are a good starting point:\n",
    "\n",
    "[x]: https://public.nrao.edu/gallery/radio-galaxy/"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "layer.vmin = -0.002\n",
    "layer.vmax = 0.009"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Step 4: Layering images\n",
    "\n",
    "One of the strengths of the WWT viewer is that you can layer as many images as you'd like and compare them. This can be great for multiwavelength science. As an example, let's use the Python module [astroquery](https://astroquery.readthedocs.io/en/latest/) to fetch 2MASS Ks-band images of the field of supernova 2011fe. This might take a little while since, like the VLASS example before, the Python kernel needs to download the data from MAST."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "from astroquery.skyview import SkyView\n",
    "\n",
    "img_list = SkyView.get_images(\n",
    "    position='SN 2011FE', \n",
    "    survey='2MASS-K', \n",
    "    pixels=700  # you can adjust the size if you want\n",
    ")\n",
    "assert len(img_list) == 1  # there's only one matching item in this example\n",
    "twomass_img = img_list[0]\n",
    "twomass_img.info()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "\n",
    "Once the FITS data are available, we can display them in pywwt using the same pattern as before. (The `add_image_layer()` function accepts either filenames or Astropy FITS data objects.)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "twomass_layer = wwt.layers.add_image_layer(twomass_img)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Once again you should see the view automatically center on your image."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now we'll load up another image of the same field that came from *Swift*, this time stored as a local file as in the first example:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "swift_layer = wwt.layers.add_image_layer(datapath('m101_swiftx.fits'))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now you can use the app's controls to fade in and out the different wavelengths.\n",
    "\n",
    "Try changing the background imagery to the PanSTARRS1 3pi survey, and see if you can find a point source that's bright in the optical, IR, *and* X-ray wavebands. Click on [its SIMBAD page][simbad] to find out what kind of object it is!\n",
    "\n",
    "[simbad]: http://simbad.u-strasbg.fr/simbad/sim-id?Ident=%408686502&Name=CXO%20J140312.4%2b541753"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Next Steps\n",
    "\n",
    "To learn how to display data tables along with your imagery, start with the [NASA Exoplanet Archive](./NASA%20Exoplanet%20Archive.ipynb) tutorial"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Credits\n",
    "\n",
    "This notebook was prepared by:\n",
    "\n",
    "- O. Justin Otor\n",
    "- Thomas Robitaille\n",
    "- Peter K. G. Williams"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
